//  Use Alamofire for net working
//  ALRequest.swift
//  ezyform
//
//  Created by FengMoennig on 11/30/15.
//  Copyright © 2015 Client.Solution Pty Ltd. All rights reserved.
//

import UIKit
import Alamofire
import SwiftyJSON
import HandyJSON
import DaisyNet
import Rswift
enum RequestErrorType: String {
    case NetworkError = "Network access failure. Please check your network connection and try again."
}
enum APICustomStatusCode: String {
    case InvalidToken = "403"
    case ForceUpdate = "601"//强制更新
    case ConfireEmailForLogin = "602"//登录的时候需要确认点击邮件中的确认按钮
    case InvalidParamsForUploadSignature = "603"//（3.5.8版本开始）提交签名时，相关协议中的字段和server上的不一致，返回此code
    case JobNotFound = "604"//pvd,swh,service job没有找到返回的code
    case OtherAPICode = "701"
    case RequestFaild = "702"
}
public let netmanager: Session = {
    //Moennig
    let urlCache = { () -> URLCache in
        let capacity = 50 * 1024 * 1024 // MBs
        let urlCache = URLCache(memoryCapacity: capacity, diskCapacity: capacity, diskPath: nil)

        URLCache.shared.diskCapacity = capacity //set diskCapacity working
        return urlCache
    }()
    URLSessionConfiguration.af.default.urlCache = urlCache
    URLSessionConfiguration.af.default.timeoutIntervalForRequest = 10//get请求超时时间
    //Moennig end
    return Session(configuration: URLSessionConfiguration.af.default)
}()
public let netmanagerForUpload: Session = {
    
    URLSessionConfiguration.af.default.timeoutIntervalForRequest = 20//checklist,sign,inverter,panel number文件上传超长会导致数据重复上传//上传数据超时时间

    return Session(configuration: URLSessionConfiguration.af.default)
}()
class ALRequest: NSObject {
    
    var method : HTTPMethod!
    var mainURL:String!
    var headers : HTTPHeaders?
    var paramsDict:Parameters?
    var successBlock:ReturnValueBlock?
    var errorBlock:ErrorCodeBlock?
    
    init(mainURL:String,method: HTTPMethod,headers: HTTPHeaders?, paramDict:Parameters?,successBlock:ReturnValueBlock?,errorBlock:ErrorCodeBlock?)
    {
        
        self.mainURL = mainURL
        self.method = method
        self.headers = headers
        self.paramsDict = paramDict
        self.successBlock = successBlock
        self.errorBlock = errorBlock
        
        super.init()
        
    }
    //MARK: - 开启get请求的缓存，且先请求缓存在请求网络数据
    func startRequest(cacheFlag: Bool = false){
        let request = DaisyNet.request(self.mainURL, method: self.method,params: self.paramsDict, dynamicParams: ["token": APPConfig.loginInfo.access_token], headers: self.headers).cache(self.method == .get ? true: false)
        
        if Connectivity.isConnectedToInternet {//有网络,请求网络
            request.responseData { resp in
                self.dealReponse(resp: resp)
            }
        }else{//无网络
            if let value = request.cacheJson(), cacheFlag {//有cache，且需要用cache时
                if let resultDic = value as? NSDictionary {
                    let successFlag = resultDic.object(forKey: "result") as? Bool ?? false
                    if successFlag {//success
                        if let msg = resultDic.object(forKey: "msg") as? String {
                            self.successBlock?(msg,nil)
                        }else{
                            self.successBlock?(resultDic.object(forKey: "data"),nil)
                        }
                    }
                }else{
                    self.errorBlock?(APICustomStatusCode.RequestFaild.rawValue,"Cache data is invalid: \n" + self.mainURL)
                }
            }else{//不用cache
                self.errorBlock?(APICustomStatusCode.RequestFaild.rawValue,RequestErrorType.NetworkError.rawValue)
            }
        }
        
    }
    private func dealReponse(resp: DaisyValue<Data>){
        switch resp.result {
        case .success(let value ):
            DebugLog(resp.isCacheData ? "我是缓存数据" : "我是网络数据")
            do{
                let asJSON = try JSONSerialization.jsonObject(with: value)
                if let resultDic = asJSON as? NSDictionary {
                    //
                    let successFlag = resultDic.object(forKey: "result") as? Bool ?? false
                    if successFlag {//success
                        let dic = NSMutableDictionary()
                        //header data
                        if let headers = resp.response?.allHeaderFields as? [String: String] as?  NSDictionary {
                            var tempNextPage = headers.object(forKey: "X-Next-Page")
                            var nextPage = (tempNextPage == nil ? "" : (tempNextPage as! String))
                            //处理如果是https/2 x-next-page首字母为小写的情况
                            if nextPage == "" {
                                tempNextPage = headers.object(forKey: "x-next-page")
                                nextPage = (tempNextPage == nil ? "" : (tempNextPage as! String))
                            }
                            let dic = NSMutableDictionary()
                            dic.setValue(nextPage, forKey: "X-Next-Page")
                        }
                        //
                        if let data = resultDic.object(forKey: "data"){
                            self.successBlock?(data,dic)
                        }else {
                            self.successBlock?(resultDic.object(forKey: "msg") as? String,nil)
                        }//也可能只返回了result = true
                    }else{//error
                        var msg: String = ""
                        var code: String = ""
                        if let data = resultDic.object(forKey: "msg") as? String{
                            msg = data
                        }
                        if let data = resultDic.object(forKey: "code") as? Int{
                            code = "\(data)"
                        }else{
                            if msg.hasPrefix(APICustomStatusCode.InvalidToken.rawValue) ||
                                msg.hasPrefix(APICustomStatusCode.ConfireEmailForLogin.rawValue) ||
                                msg.hasPrefix(APICustomStatusCode.ForceUpdate.rawValue) ||
                                msg.hasPrefix(APICustomStatusCode.InvalidParamsForUploadSignature.rawValue) ||
                                msg.hasPrefix(APPConfig.ShowErrorInfoUpgradePrefix)   {
                                code = (msg as NSString).substring(to: 3)
                                msg = (msg as NSString).substring(from: 3)
                            }
                        }
                        //如果code ， msg一样， 将msg设置为空
                        if code == msg{
                            msg = ""
                        }
                        if code == "" {
                            code = APICustomStatusCode.OtherAPICode.rawValue
                        }
                        self.errorBlock?(code,msg)
                    }
                }
            }catch{
                let errorMsg = APPConfig.isTestFlag ? ("Convert data to JSON failed: " + self.mainURL + "\n params: \(self.paramsDict ?? [:])") : RequestErrorType.NetworkError.rawValue
                self.errorBlock?("",errorMsg)
            }
            
        case .failure(_)://code 为空的，就是网络错误或请求出错的
//            let statusCode = resp.response?.statusCode ?? 0
            self.errorBlock?(APICustomStatusCode.RequestFaild.rawValue,RequestErrorType.NetworkError.rawValue)
        }
    }
    fileprivate func toPrintResponse(_ response: AFDataResponse<Any>){
        #if DEBUG
            if let dic = response.value as? NSDictionary{
                if let data = try? JSONSerialization.data(withJSONObject: dic, options: []){
                    //打印JSON字符串
//                    if let JSONString = NSString(data:data as Data,encoding: String.Encoding.utf8.rawValue){
//                        print("1.***********请求\(response.request?.url?.absoluteString ?? "")\n2.***********返回结果JSON字符串:\n",JSONString)
//                    }
                    //
                    if let jsonObject = try? JSONSerialization.jsonObject(with: data, options: .mutableContainers){
                        print("查询结果JSON对象:\n",jsonObject)
                    }
                }

            }else if let error = response.error {
                print("1.***********请求\(response.request?.url?.absoluteString ?? "")\n2.***********请求失败:\n",error.localizedDescription)
            }

        #endif
    }
}
extension DataRequest {
   public func debugLog() -> Self {
      #if DEBUG
//         debugPrint(self)
      #endif
      return self
   }
}
